package Git2024_5_20;

public class Knife4j {
    /**
     * JsonFormat
     * Pattern 日期 格式:小大小 大小小
     * Timezone 时区
     *
     * Lombok
     * 1.消除模板代码
     * 2.日志 五种 TRACE 非常详细 一般不用 DEBUG 测试时使用 INFO 线上使用 WARN 警告级别 ERROR 错误级别
     * 设置了级别后 只会显示该级别以及高于该级别的日志
     * 不设置全局日志级别 默认为INFO
     *
     * 在类上添加 @Slf4j注解 利用log.级别名即可规定方法或模块的日志级别
     *
     * Knife4j
     * 1.功能性测试
     * 2.生成API文档
     * 步骤
     *  1.添加依赖
     *  2.创建配置类 指定扫描的路径-一般为Controller
     *  3.重启工程
     *  4.访问网站 [http:]localhost:8080/[.doc.html]被`[]`标识的为固定格式
     */
    /*--------------------------------------------------正课---------------------------------------------------------*/
    /**
     * Knife4j
     * 前提 所有Knife4j中的注解都是@Api开头的
     *
     * 1.模块名顺序调整: 名称是按照阿斯克码排序的
     *  类级别
     * @Api: 控制器的类名在Knife4j文档中的显示
     *
     * 2.方法名调整: 在当前使用的Knife4j版本中暂时不支持上述方法排序
     *  方法级别
     * @ApiOperation(""): 控制器方法名在Knife4j文档中的显示
     *
     * 3.忽略某些无需与前端提交的信息
     *  参数级别
     * @ApiIgnore: 加在某些参数上对其进行忽略 表示该参数不显示在Knife4j中
     *
     * 4.请求参数说明,是否必须选项指定[true/false]
     *  属性级别(一般在DTO或VO类中使用)
     *  DTO: 需要注明是否必须填写
     * @ApiModelProperty(value = "属性名/属性描述", required = true/false[是否必须默认为false])
     *  VO: 无需声明是否必须填写
     * @ApiModelProperty(value = "属性名/属性描述")
     *
     * 5.对方法参数的描述
     *  方法级别
     *  5.1 添加在方法上 表示参数在Knife4j文档中的显示
     * @ApiImplicitParam(name = "参数名[例如`id`,用于指明指定的是哪个参数]",value = "参数描述[例如`微博编号`]",required = true)
     *  此时文档中的默认参数类型为String 需要在注解中进行额外描述
     * @ApiImplicitParam(name = "参数名",value = "参数描述",required = true,dataType = "全小写的类型描述[例如`long`]")
     *  在API文档中的类型自动识别为包装类 int -> Integer
     * 注意: 该注解每次只能描述一个方法参数 且不能同时出现多个该注解 -> 引入复数注解
     *
     *  5.2 添加在方法上 表示多个参数在Knife4j文档中的显示
     * 注意: 多个@ApiImplicitParam注解之间用`,`隔开
     * @ApiImplicitParams(value={
     * @ApiImplicitParam(name = "参数名1",value = "参数描述1",required = true,dataType = "全小写的类型描述1"),
     * @ApiImplicitParam(name = "参数名2",value = "参数描述2",required = true,dataType = "全小写的类型描述2")
     * })
     */

    // 1.统一响应结果的处理
    /**
     * 统一响应结果的处理
     * 实际开发中 极少返回不明确的信息[例如1代表成功 2代表失败等等]
     * 将需要返回数据的功能的返回值完全统一为同一类型
     * 服务端返回给客户端数据一般包含3项:
     *  1.响应状态码state/statusCode(HTTP通用/自定义):
     *  2.提示消息message:
     *  3.具体数据data:
     *
     * 格式:  利用全参构造
     *    return new JsonResult(2001[state],"操作成功"[message],null[data]);
     *
     * 注意 并非所有功能都包含上述三个部分: 如登录功能 无需返回具体数据 只需要告知是否登录成功
     *     即几乎所有控制器都会返回响应状态码和提示消息 但具体数据是否返回取决于具体功能是否有此需求
     */
    /*
        云通讯:第三方短信平台 无独立短信通道 必须与运营商进行协商 借用运营商的短信通道进行短信收发服务
     */
    /**
     * 响应状态码
     * 通用状态码无法满足业务需求:
     *  例如登陆成功 返回200 密码错误 返回的也是200 因为该请求和响应顺利进行 请求/响应的状态是无异常的
     * 自定义状态码:
     *  设计思路
     *   内部状态码设计:首先需要给各个模块规定范围 避免多模块之间设计重复
     *               设计状态码位数可以根据需求自定义 不同工程之间无统一规范
     *               需要规定范围较广的与操作结果相关的状态码 以其为索引区分成功和失败的具体原因
     */
    // 2.自定义枚举状态码(StatusCode)
    /**
     * 利用枚举整合状态码
     * 枚举: 定义常量
     * 1.创建common.response.StatusCode枚举类 定义属性[状态码,提示消息等] 加入注解创建Getter,全参构造,无参构造方法
     *  1.1 在属性上方创建枚举类常量并规定属性值
     *
     * --将属性写在类中枚举定义常量方法之后 详见StatusCode类中 写入Getter,全参构造,无参构造方法--
     *
     * 2 创建common.response.JsonResult类 利用注解创造Getter and Setter,全参构造,无参构造方法
     *   将`状态码`,`提示信息`,`具体数据`三个数据定义为属性
     *  2.1 利用构造方法对是否有`具体数据`返回进行区分 并创建静态方法用于封装常用构造方法 简化代码
     *
     * --用于规定枚举类中的常量显示形式-自定义构造方法 写入Getter and Setter,全参构造,无参构造方法--
     *
     * 3.将控制器中的方法返回值改为引进了枚举的JsonResult类
     *  3.1 使用JsonResult.枚举常量名方式,利用自定义构造引入枚举类 进行标注状态码及状态提示
     */
    //总结
    /**
     * 自定义状态码优势
     * 1.状态回馈更加精准
     * 2.处理错误更加方便
     * 3.易于扩展 对现有功能进行优化或业务扩展时 可自行移除或添加自定义状态码
     */
    /**
     * 统一响应结果的处理
     * 1.简化前端开发
     * 2.提高代码的可读性和可维护性(全局异常处理器)
     */
    /**
     * 编码流程
     * 前提: 一定是完成了自定义状态码的整体设计
     * 1.自定义枚举类
     * 2.创建统一响应结果返回的类
     * 3.在controller中使用即可
     */
    // 全局异常处理器
    /**
     * Spring MVC框架中的异常处理机制(拦截器,处理器)
     * 处理由控制器中抛出的异常
     *
     * Spring MVC自带的异常处理机制: 网页中显示一个包含状态码等信息的页面
     * 缺点: 用户端可视性差 -> 引入全局异常处理器自定义异常处理逻辑
     * GlobalExceptionHandler 全局异常处理器
     * 一般路径为: common.exception.GlobalExceptionHandler
     *
     * 流程
     * 若抛出异常 Spring IoC容器会扫描工程中是否有自定义异常处理器 若未扫描到 会执行Spring MVC内置异常处理机制
     */
    /**
     * 全局异常处理器
     * -注解1-
     * @ControllerAdvice注解 [类级别注解]
     *  1.标识本类为Spring MVC中全局异常处理器
     *  2.拦截所有Controller抛出的异常[Controller开头]
     * 注意:
     * 在该类中 定义处理异常的方法 返回值依旧为JsonResult类型[返回给服务端]
     *
     * -注解2-
     * @ExceptionHandler注解 [方法级别注解]
     *  方法上标注此注解后 则被声明为指定异常的处理方法
     *
     * -注解3-
     * @RestControllerAdvice注解 [类级别注解]
     *  组合注解 相当于@ResponseBody + @ControllerAdvice
     *
     * 方法
     * 方法参数为控制器抛出的异常对象 若想查看异常提示消息 则需要使用异常的方法
     * String message = 异常对象.getMessage()方法
     *
     * 例如:
     * 1.在控制器中规定:
     *  若触发了Xxx异常 会输出提示信息:"Xxx值不能小于0"并抛出:
     *    throw new XxxException("Xxx值不能小于0");
     *    此时会检查工程中是否存在自定义异常处理逻辑,若检查到存在,则进入该类进行异常比对 看是否有适用于此异常的方法
     * 2.而在全局异常处理器中:
     *  方法参数格式为:
     *    public JsonResult doHandleXxxException(XxxException xxxExp){\..}
     *    其中参数`xxxExp`为控制器抛出的异常对象
     *    返回值`JsonResult`为预先设置好的统一响应结果类
     *  此时利用方法:
     *    String message = xxxExp.getMessage();
     *  并随返回值一同输出即可[利用先前创建的自定义统一响应结果类作为返回值]:
     *    return new JsonResult(StatusCode.OPERATION_FAILED,message);
     */
    /**
     * 全局异常处理器声明流程:
     * 1.定义某个类为全局异常处理器类[利用@ControllerAdvice注解标识该类]
     * 2.系统会扫描该类中所有包含@ExceptionHandler注解的方法 通过方法参数中的异常名称锁定所报异常的对应方法
     *   2.1 此时仍无法实现返回全局异常处理器信息的功能 因为缺少了响应体 即缺少`@ResponseBody`注解
     *   2.2 因此引入组合注解简化代码: `@RestControllerAdvice`注解[可以参考 Controller 类中的`@RestController`注解]
     * 3.此时 类上被@RestControllerAdvice标注 对应方法上被@ExceptionHandler标注
     * 4.声明基本完成
     */
    /**
     * 查找异常处理的流程
     *   1.控制器抛出异常,首先检查是否定义全局异常处理器;
     *   2.如果没有定义全局异常处理器,则使用默认异常处理机制[不友好];
     *   3.如果定义了全局异常处理器,则寻找有没有定义对应的异常处理方法;
     *   4.如果没有定义对应的异常处理方法,则使用默认异常处理机制[不友好];
     *   5.如果定义了对应的异常处理方法,则使用对应的异常处理方法处理异常;
     */
}
